#pragma once

#include "IReverbManager.h"

class CEAXPresetMgr : public ISoundEventListener
{
protected:

		XmlNodeRef                m_pRootNode;
		XmlNodeRef                m_pParamTemplateNode;
		string                    m_sPresetSelected;
		float                     m_fReverbWetVal;

protected:

		bool                      DumpTableRecursive(FILE *pFile, XmlNodeRef pNode, int nTabs=0);
		void                      InitNodes();

public:

		CEAXPresetMgr();
		virtual ~CEAXPresetMgr();

	inline XmlNodeRef         GetRootNode() { return m_pRootNode; }
	bool                      AddPreset(CString sName);
	bool                      DelPreset(CString sName);
	bool                      PreviewPreset();
	bool                      RegisterPreset(char const* const sPresetName);
	bool                      UnregisterPreset(char const* const sPresetName);
	bool                      Save(CString sFilename=REVERB_PRESETS_FILENAME_LUA);
	bool                      Load(CString sFilename=REVERB_PRESETS_FILENAME_LUA);
	bool                      Reload(CString sFilename=REVERB_PRESETS_FILENAME_LUA);
	bool                      UpdateParameter(XmlNodeRef pNode);

	void                      MakeTagUnique(XmlNodeRef pParent, XmlNodeRef pNode);
	void                      StopPreviewSound();
	void                      SetPreviewSound(char const* const sSound);
	inline char const* const  GetPreviewSoundName() const { return m_sSound.c_str(); }
	inline void               SetPreviewSoundWetVal(float const fNewWetVal) { m_fReverbWetVal = fNewWetVal; }
	float                     GetPreviewSoundWetVal() const;
	inline tSoundID           GetPreviewSoundID() const { return m_nSoundID; }
	inline void               SetReverbWetValueDefault(float const fValueDefault) { m_fReverbWetValueDefault = fValueDefault; }
	virtual void              OnSoundEvent(ESoundCallbackEvent eSoundEvent, ISound* pSound);
	void                      ImportPresets();
	void                      ExportPresets();

private:

	void CallOnPropertyChange(CString sPresetName);

	CString                   OpenDialog(bool const bOpenFile);
	bool                      TransferParameter(XmlNodeRef const& rNodePresetFrom, XmlNodeRef const& rNodePresetTo, char const* const sParameterNameFrom, char const* const sParameterNameTo, int unsigned const nDataType);

	string										m_sSound;
	float											m_fReverbWetValueDefault;
	tSoundID                  m_nSoundID;
	CryFixedStringT<_MAX_PATH> m_sLastOpenendDirectory;
};

class CEAXPresetSODump : public IScriptTableDumpSink
{
private:
		IScriptSystem *m_pScriptSystem;
		SmartScriptTable m_pObj;
		XmlNodeRef m_pNode;
		XmlNodeRef m_pParamTemplateNode;
		int m_nLevel;
public:
		CEAXPresetSODump(IScriptSystem *pScriptSystem, SmartScriptTable &pObj, XmlNodeRef pNode, XmlNodeRef pParamTemplateNode, int nLevel=0) : m_pObj(pObj)
		{
				m_pScriptSystem=pScriptSystem;
				m_pNode=pNode;
				m_pParamTemplateNode=pParamTemplateNode;
				m_nLevel=nLevel;
		}
private:
	void OnElementFound(const char *sName, ScriptVarType type)
	{
		switch (type)
		{
		case svtObject:
			{
				SmartScriptTable pObj(m_pScriptSystem, true);
				m_pObj->GetValue(sName, pObj);

				if (strcmp(sName, "EchoDSP") == 0)
				{
					// vector
					XmlNodeRef pNode=m_pNode->findChild(sName);
					if (pNode)
					{
						CEAXPresetSODump Sink(m_pScriptSystem, pObj, pNode, m_pParamTemplateNode, m_nLevel+1);
						pObj->Dump(&Sink);
					}
				}
				else
				{
					XmlNodeRef pNode=m_pParamTemplateNode->clone();
					pNode->setTag(sName);
					m_pNode->addChild(pNode);
					CEAXPresetSODump Sink(m_pScriptSystem, pObj, pNode, m_pParamTemplateNode, m_nLevel+1);
					pObj->Dump(&Sink);
				}
				break;
			}
		case svtString:
			{
				const char *pszValue;
				m_pObj->GetValue(sName, pszValue);
				XmlNodeRef pNode=m_pNode->findChild(sName);
				//ASSERT(pNode!=NULL);
				if (pNode)
					pNode->setAttr("value", pszValue);
				break;
			}
		case svtNumber:
			{
				float pszValue;
				m_pObj->GetValue(sName, pszValue);
				XmlNodeRef pNode=m_pNode->findChild(sName);
				//ASSERT(pNode!=NULL);
				if (pNode)
					pNode->setAttr("value", pszValue);
				break;
			}
		}
	}
	void OnElementFound(int nIdx, ScriptVarType type)
	{
	}
};

class CEAXPresetUpdateSODump : public IScriptTableDumpSink
{
private:
		IScriptSystem *m_pScriptSystem;
		SmartScriptTable m_pObj;
		CString m_sPresetName;
		CString m_sPropName;
		CString m_sPropValue;
		bool m_bCorrectPreset;
public:
		CEAXPresetUpdateSODump(IScriptSystem *pScriptSystem, SmartScriptTable &pObj, CString &sPresetName, CString &sPropName, CString &sPropValue, bool bCorrectPreset=false) : m_pObj(pObj)
		{
				m_pScriptSystem=pScriptSystem;
				m_sPresetName=sPresetName;
				m_sPropName=sPropName;
				m_sPropValue=sPropValue;
				m_bCorrectPreset=bCorrectPreset;
		}
private:
		void OnElementFound(const char *sName, ScriptVarType type)
		{
				switch (type)
				{
				case svtObject:
						{
								SmartScriptTable pObj(m_pScriptSystem, true);
								m_pObj->GetValue(sName, pObj);
								if (strcmp(sName, m_sPresetName)==0)
								{
										CEAXPresetUpdateSODump Sink(m_pScriptSystem, pObj, m_sPresetName, m_sPropName, m_sPropValue, true);
										pObj->Dump(&Sink);
								}else
								{
										CEAXPresetUpdateSODump Sink(m_pScriptSystem, pObj, m_sPresetName, m_sPropName, m_sPropValue, false);
										pObj->Dump(&Sink);
								}
								break;
						}
				case svtString:
						{
								if (m_bCorrectPreset && strcmp(sName, m_sPropName)==0)
								{
										for (int i=0;i<m_sPropValue.GetLength();i++)
										{
												if (m_sPropValue[i]=='\\')
														m_sPropValue.SetAt(i, '/');
										}
										m_pObj->SetValue(sName, (const char*)m_sPropValue);
								}
								break;
						}
				case svtNumber:
						{
								if (m_bCorrectPreset && strcmp(sName, m_sPropName)==0)
								{
										float fVal = atof(m_sPropValue);
										//m_pObj->SetValue(sName, (const char*)m_sPropValue);
										m_pObj->SetValue(sName, fVal);
								}
								break;
						}
				}
		}
		void OnElementFound(int nIdx, ScriptVarType type)
		{
		}
};
